var _ = require('lodash'),
    Q = require('q'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    assemblyRelationController = require('../../../Barcode/server/controllers/AssemblyRelation.server.controller'),
    bizRecordController = require('../../../Barcode/server/controllers/BizRecord.server.controller'),
    extendEnumController = require('../../../Common/server/controllers/ExtendEnum.server.controller');

exports.getProductFlow = function(req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode;

    var productFlow = {};
    queryBarcodeMaster(barcode).then(function(info) {
        productFlow.basicInfo = info.basicInfo;
        productFlow.productParam = info.productParam;
        return queryBizRecords(info.barcodeMasterIds);
    }).then(function(bizRecords) {
        _.merge(productFlow.basicInfo, bizRecords.realDateTime);
        delete bizRecords.realDateTime;
        _.merge(productFlow, bizRecords);
        res.json({
            Data: productFlow,
            Error: null
        });
    }).catch(function(err) {
        res.json({
            Data: null,
            Error: err
        });
    })
    .done();
};

function queryBarcodeMaster(barcode) {
    var deferred = Q.defer();

    var result = {},
        barcodeMaster;
    findBarcodeMaster(barcode).then(function (record) {
        barcodeMaster = record;
        return assemblyRelationController.findAssemblyRelations(record._id);
    }).then(function (barcodeMasterIds) {
        var lastBarcodeMaster;
        if (!barcodeMasterIds) {
            result.barcodeMasterIds = [barcodeMaster._id];
            return Q.resolve(barcodeMaster);
        } else {
            result.barcodeMasterIds = barcodeMasterIds;
            return barcodeMasterController.findBarcodeMasterById(barcodeMasterIds[0]);
        }
    }).then(function (lastBarcodeMaster) {
        var temp = {
            barcodeMasterId: lastBarcodeMaster._id,
            Barcode: lastBarcodeMaster.Barcode,
            ItemMasterCode: lastBarcodeMaster.ItemMasterCode,
            OperationName: lastBarcodeMaster.OperationName,
            QCStatus: lastBarcodeMaster.QCStatus,
            MOLotNumber: lastBarcodeMaster.MOLotNumber,
            ShipLotNumber: lastBarcodeMaster.CompletePlan ? lastBarcodeMaster.CompletePlan.LotNumber : ''
        };
        if (lastBarcodeMaster.MO) {
            _.merge(temp, {
                MOCode: lastBarcodeMaster.MO.Code,
                Customer: lastBarcodeMaster.MO.Customer,
                StartDateTime: lastBarcodeMaster.MO.StartDateTime,
                EndDateTime: lastBarcodeMaster.MO.EndDateTime
            });
        }
        if (lastBarcodeMaster.ItemMaster) {
            _.merge(temp, {
                ItemMasterName: lastBarcodeMaster.ItemMaster.Name,
                Specification: lastBarcodeMaster.ItemMaster.Specification,
                ItemCategory: lastBarcodeMaster.ItemMaster.ItemCategory
            });
        }
        result.basicInfo = temp;
        result.productParam = {
            GripSize: lastBarcodeMaster.DescSeg1,
            GripSkin: lastBarcodeMaster.DescSeg2,
            DescSeg3: lastBarcodeMaster.DescSeg3
        };
        return convertItemCategoryEnum(result.basicInfo);
    }).then(function () {
        deferred.resolve(result);
    }).catch(function (err) {
        deferred.reject(err);
    })
    .done();

    return deferred.promise;
}

function findBarcodeMaster (barcode) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function(err, barcodeMaster) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!barcodeMaster || barcodeMaster.BarcodeType != 0) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询物料错误';
            newErr.message = '无法识别的芯片，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(barcodeMaster);
    });

    return deferred.promise;
}

function convertItemCategoryEnum (basicInfo) {
    var deferred = Q.defer();

    if (basicInfo.ItemCategory !== undefined) {
        extendEnumController.findEnumOptions('ItemCategory', function (err, option) {
            if (err) {
                deferred.reject(err);
                return;
            }
            basicInfo.ItemCategory = option[basicInfo.ItemCategory];
            deferred.resolve();
        });
    } else {
        deferred.resolve();
    }
    
    return deferred.promise;
}

function queryBizRecords(barcodeMasterIds) {
    var deferred = Q.defer();

    bizRecordController.findByBarcodeMaster(barcodeMasterIds, function(err, bizRecords) {
        if (err) {
            deferred.reject(err);
            return;
        }
        var results = {
            bizCatalog: [],
            bizRecords: {},
            realDateTime: {}
        };
        if (bizRecords.length >= 1) {
            results.realDateTime.RealStartDateTime = bizRecords[0].CollectDateTime;
            results.realDateTime.RealEndDateTime = bizRecords[bizRecords.length - 1].CollectDateTime;
        }
        var depUniqueId = 1000,
            lastResultRecord = {},
            workTime = 0,
            tmpRecord, lastCatalogId, lastWorkLocation, lastBizCollectTime;
        for (var i = 0, len = bizRecords.length; i < len; i++) {
            tmpRecord = bizRecords[i];
            if (!tmpRecord.WorkLocation || !tmpRecord.WorkLocation.Department) {
                continue;
            }
            if (tmpRecord.WorkLocation.Department._id !== lastCatalogId) {
                results.bizCatalog.push({
                    UniqueId: depUniqueId,
                    Code: tmpRecord.WorkLocation.Department.Code,
                    Name: tmpRecord.WorkLocation.Department.Name
                });
                results.bizRecords[depUniqueId] = [];

                lastCatalogId = tmpRecord.WorkLocation.Department._id;
                depUniqueId++;
            }
            if (tmpRecord.Operation && tmpRecord.Operation.IsTiming && (tmpRecord.WorkLocation.toString() === lastWorkLocation)) {
                workTime += ((tmpRecord.CollectDateTime - lastBizCollectTime) / 1000);
                if (tmpRecord.Operation.IsQCpoint) {
                    lastResultRecord.QCStatus = tmpRecord.QCStatus;
                }
                lastResultRecord.QCFlag = tmpRecord.Operation.IsQCpoint;
            } else {
                if (workTime > 0) {
                    lastResultRecord.WorkTime = workTime.toFixed(2);
                    workTime = 0;
                }
                lastResultRecord = {
                    CollectDateTime: tmpRecord.CollectDateTime,
                    TerminalName: tmpRecord.TerminalName,
                    WorkName: tmpRecord.WorkName,
                    WorkLocationName: tmpRecord.WorkLocationName,
                    Users: tmpRecord.Users
                };
                if (tmpRecord.Operation) {
                    if (tmpRecord.Operation.IsQCpoint) {
                        lastResultRecord.QCStatus = tmpRecord.QCStatus;
                    }
                    lastResultRecord.QCFlag = tmpRecord.Operation.IsQCpoint;
                }
                results.bizRecords[depUniqueId - 1].push(lastResultRecord);
            }
            lastWorkLocation = tmpRecord.WorkLocation.toString();
            lastBizCollectTime = tmpRecord.CollectDateTime;
        }
        if (tmpRecord && tmpRecord.Operation && tmpRecord.Operation.IsTiming && workTime > 0) {
            lastResultRecord.WorkTime = workTime.toFixed(2);
            if (tmpRecord.Operation.IsQCpoint) {
                lastResultRecord.QCStatus = tmpRecord.QCStatus;
            }
            lastResultRecord.QCFlag = tmpRecord.Operation.IsQCpoint;
        }
        deferred.resolve(results);
    });

    return deferred.promise;
}
